//地图建立
// B B X X X B B
// B B X X X B B
// X X O X X O X
// X O O O O X X
// X X O X X X X
// B B O O X B B
// B B X X X B B
// 建立直观的二维表，X - 空白位, O - 实体块, B - 填充位

//规则
//基于0开始，对于第2，3，4的行和列，可以进行循环位移操作。所以B块都是不能移动的，只是为了方便二维表
//目标： 将所有的9个实体块移动到中间的3x3格子里

function ZGLockFactory() {
    baseNode.call(this);
    this.board = [
        ['B', 'B', 'X', 'X', 'X', 'B', 'B'],
        ['B', 'B', 'X', 'X', 'X', 'B', 'B'],
        ['X', 'X', 'X', 'X', 'X', 'X', 'X'],
        ['X', 'X', 'X', 'X', 'X', 'X', 'X'],
        ['X', 'X', 'X', 'X', 'X', 'X', 'X'],
        ['B', 'B', 'X', 'X', 'X', 'B', 'B'],
        ['B', 'B', 'X', 'X', 'X', 'B', 'B'],
    ]; //初始化时没有O块，然后需要往里面放置O块
    //this.normalize = []; //归一化棋盘  省略
}

// 设置原型链
ZGLockFactory.prototype = Object.create(baseNode.prototype);
ZGLockFactory.prototype.constructor = ZGLockFactory;

//对数组的某个区间范围内的位进行循环左移，区间以外的位不会移动
ZGLockFactory.prototype.shiftLeft = function(data,left,right) {  
    let newData = data.slice(0,left)
    const ch = data[left]
    newData = newData.concat(data.slice(left+1,right+1))
    newData.push(ch)
    newData = newData.concat(data.slice(right+1))
    return newData
}

//对数组的某个区间进行循环右移
ZGLockFactory.prototype.shiftRight = function(data,left,right) {
    let newData = data.slice(0,left)
    const ch = data[right]
    newData.push(ch)
    newData = newData.concat(data.slice(left,right))
    newData = newData.concat(data.slice(right+1))
    return newData
}

//提供的循环位移某行或列的功能
//axis : 轴向: -1 - x轴水平移动 1 - y轴垂直移动
//index : 第index行或列: 输入的是[0,1,2]， 映射到二维表的是 [2,3,4]
//step : 移动步数，负值往轴负方向移动，正值往轴正方向移动
ZGLockFactory.prototype.move = function(axis,index,step) {
    let tableIndex = index + 2
    if(axis == -1){
        if(step > 0){
            for(let i=0;i<step;i++)
            {
                if(this.board[tableIndex][0] == 'B'){
                    this.board[tableIndex] = this.shiftRight(this.board[tableIndex],2,4)
                }
                else{
                    this.board[tableIndex] = this.shiftRight(this.board[tableIndex],0,6)
                }
            }
        }else{
            for(let i=step;i>=0;i--)
            {
                if(this.board[tableIndex][0] == 'B'){
                    this.board[tableIndex] = this.shiftLeft(this.board[tableIndex],2,4)
                }else{
                    this.board[tableIndex] = this.shiftLeft(this.board[tableIndex],0,6)
                }
            }
        }
    }else{
        let elements = []
        for(i=0;i<7;i++)
        {
            elements.push(this.board[i][tableIndex])
        }
    
        if(step > 0){
            for(let i=0;i<step;i++)
            {
                if(elements[0] == 'B'){
                    elements = this.shiftLeft(elements,2,4)
                }else{
                    elements = this.shiftLeft(elements,0,6)
                }
            }
        }else{
            for(let i=step;i>=0;i--)
            {
                if(elements[0] == 'B'){
                    elements = this.shiftRight(elements,2,4)
                }else{
                    elements = this.shiftRight(elements,0,6)
                }
            }
        }
        for(i=0;i<7;i++)
        {
            this.board[i][tableIndex] = elements[i]
        }
    }
}

function deepCopy2DArray(arr) {
    const newArr = [];
    for (let i = 0; i < arr.length; i++) {
        newArr[i] = [];
        for (let j = 0; j < arr[i].length; j++) {
            newArr[i][j] = arr[i][j];
        }
    }
    return newArr;
}

//拷贝节点
ZGLockFactory.prototype.CopyFrom = function(node)
{
    this.board = deepCopy2DArray(node.board);
}

//增加实体块
//cow,row: 二维表的行列，取值0-6
ZGLockFactory.prototype.addBlock = function(col,row)
{
    if(this.board[row][col] == 'B'){
        console.error('填充位无法修改')
    }else{
        this.board[row][col] = 'O'
    }
}

//初始化为结束节点
ZGLockFactory.prototype.initEnd = function(col,row)
{
    this.addBlock(2,2);
    this.addBlock(3,2);
    this.addBlock(4,2);
    this.addBlock(2,3);
    this.addBlock(3,3);
    this.addBlock(4,3);
    this.addBlock(2,4);
    this.addBlock(3,4);
    this.addBlock(4,4);
}

//获得地图的实体块数目
ZGLockFactory.prototype.blockCount = function()
{
    let count = 0
    for(let col=0;col<7;col++)
    {
        for(let row=0;row<7;row++)
        {
            let ch = this.board[row][col]
            if(ch == 'O'){
                ch = ' '
            }
            count ++
        }
    }
    return count
}


//获取该节点的所有变化节点
ZGLockFactory.prototype.getNextStates = function()
{
    let states = []
    //每一行的位移操作
    for(let row=0;row<3;row++)
    {
        for(let step=1;step<7;step++)
        {
            let new_state = new ZGLockFactory();
            new_state.CopyFrom(this)
            new_state.move(-1,row,step)
            //将step从区间[1,6]映射到[-3,3]里,不含0
            let disp_step = step;
            if(disp_step > 3){
                disp_step -= 7
            }
            new_state.actionDesc = `X,${row},${disp_step}`; //动作描述，在这里定义为‘某行或列进行位移’
            states.push(new_state);
        }
    }
    //每一列的位移操作
    for(let col=0;col<3;col++)
    {
        for(let step=1;step<7;step++)
        {
            let new_state = new ZGLockFactory();
            new_state.CopyFrom(this)
            new_state.move(1,col,step)
            //将step从区间[1,6]映射到[-3,3]里,不含0
            let disp_step = step;
            if(disp_step > 3){
                disp_step -= 7
            }
            new_state.actionDesc = `X,${col},${disp_step}`; //动作描述，在这里定义为‘某行或列进行位移’
            states.push(new_state);
        }
    }
    return states;
}

function is2DArraysEqual(arr1, arr2) {
    // 首先检查外层数组的长度
    if (arr1.length !== arr2.length) {
        return false;
    }

    // 遍历外层数组
    for (let i = 0; i < arr1.length; i++) {
        // 检查内层数组的长度
        if (arr1[i].length !== arr2[i].length) {
            return false;
        }

        // 遍历内层数组
        for (let j = 0; j < arr1[i].length; j++) {
            // 检查对应位置的元素是否相等
            if (arr1[i][j] !== arr2[i][j]) {
                return false;
            }
        }
    }

    // 如果所有检查都通过，则数组相等
    return true;
}

//判断两个节点是否相等
ZGLockFactory.prototype.equal = function(node)
{
    return is2DArraysEqual(this.board,node.board);
}

//
ZGLockFactory.prototype.dump = function()
{
    let info = this.actionDesc + " :\n";
    for(let row=0;row<7;row++)
    {
        for(let col=0;col<7;col++)
        {
            let ch = this.board[row][col]
            if(ch == 'B'){
                ch = ' '
            }
            if(ch == 'X'){
                ch = '.'
            }
            info += ch
        }
        info += '\n'
    }
    return info;
}

//获得唯一标识
ZGLockFactory.prototype.id = function() {
    let uid=''

    //将二维表转换为字符串的uid,但这太长了
    // for(let col=0;col<7;col++)
    // {
    //     for(let row=0;row<7;row++)
    //     {
    //         uid += this.board[row][col]
    //     }
    // }


    //将二维表里所有的O块的位置信息转换为字符串的uid
    for(let col=0;col<7;col++)
    {
        for(let row=0;row<7;row++)
        {
            if(this.board[row][col] == 'O'){
                uid += `${row}${col}`
            }
        }
    }

    return uid
}
